/**
 * Venda de Bilhetes Eletronicos para Espetaculos (Arena Entretenimento S.A.)
 * VendaBilheteDAOHsql.java
 */
package br.unicamp.ic.inf300.arena.persistencia.dao.impl;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

import br.unicamp.ic.inf300.arena.modelo.vendas.Bilhete;
import br.unicamp.ic.inf300.arena.modelo.vendas.CartaoCredito;
import br.unicamp.ic.inf300.arena.modelo.vendas.Venda;
import br.unicamp.ic.inf300.arena.modelo.vendas.Pagamento;
import br.unicamp.ic.inf300.arena.modelo.vendas.ValeEntrada;
import br.unicamp.ic.inf300.arena.persistencia.dao.IBilheteDAO;
import br.unicamp.ic.inf300.arena.persistencia.dao.IVendaBilheteDAO;
import br.unicamp.ic.inf300.arena.persistencia.dao.IPagamentoDAO;
import br.unicamp.ic.inf300.framework.persistencia.DAOFactory;
import br.unicamp.ic.inf300.framework.persistencia.SQLUtil;
import br.unicamp.ic.inf300.framework.util.DataUtil;

public class VendaBilheteDAOHsql implements IVendaBilheteDAO {

	/**
	 * obter
	 */
	public Venda obter(long numProtocolo)  throws Exception {

		Venda venda = null;
		ValeEntrada vale = null;
		CartaoCredito cartao = null;
		try {
			StringBuffer stbQuery = new StringBuffer();
			stbQuery.append(" SELECT ");
			//                  1               2           3       4
			stbQuery.append("   c.numprotocolo, c.dataHora, p.tipo, p.codpagto, ");
			//                  5        6               7           8
			stbQuery.append("   p.valor, p.numerocartao, p.bandeira, p.validade, ");
			//                  9
			stbQuery.append("   p.codestorno ");
			stbQuery.append(" FROM ");
			stbQuery.
					append(IVendaBilheteDAO.TABELA_BD + " c, " + IPagamentoDAO.TABELA_BD + " p ");
			stbQuery.append(" WHERE ");
			stbQuery.append("   c.codpagto     = p.codpagto AND ");
			stbQuery.append("   c.numprotocolo = ? ");
			//
            Object[] params = new Object[1];
            params[0] = numProtocolo;

            Object[] record = (Object[]) SQLUtil.selectARecord(stbQuery
					.toString(), params);

    		if (record != null && record.length > 0) {
				venda = new Venda();
				venda.setNumProtocolo( ((Long) record[0]).longValue() );
				venda.setDataHora( ((Timestamp) record[1]) );

				//
				int tipo = 0;
				if (record[2] != null) {
					tipo = ((Integer) record[2]).intValue();
				}
				//
				int codpagto = 0;
				if (record[3] != null) {
					codpagto = ((Integer) record[3]).intValue();
				}
				//
				double valor = 0.00D;
				if (record[4] != null) {
					valor = ((Double) record[4]).doubleValue();
				}
				//
				long numeroCartao = 0L;
				if (record[5] != null) {
					numeroCartao = ((Long) record[5]).longValue();
				}
				//
				String strBandeira = "";
				if (record[6] != null) {
					strBandeira = ((String) record[6]);
				}
				//
				Date validade = null;
				if (record[7] != null) {
					validade = (java.sql.Date) record[7];
				}
				//
				long codEstorno = 0L;
				if (record[8] != null) {
					codEstorno = ((Long) record[8]).longValue();
				}

				//instancia subclasse de Pagamento
				if (tipo == Pagamento.TIPO_CARTAO) {
					cartao = new CartaoCredito(codpagto, valor, numeroCartao,
							strBandeira);
					venda.setPagamento(cartao);

				} else if (tipo == Pagamento.TIPO_VALE_ENTRADA) {
					vale = new ValeEntrada(codpagto, valor, validade,
							codEstorno);
					venda.setPagamento(vale);
				}
			}
		} catch (SQLException sql) {
			System.err.println(sql.getMessage());
			throw new Exception(sql.getMessage());
		}
		return venda;
	}

	/**
	 * 
	 */
	public boolean inserir(Date dataHora, int codPagto)  throws Exception {
		System.out.println("\n\n\n *** VendaBilheteDAOHsql :: inserir(Date dataHora, int codPagto) \n\n\n");
		
		int result = 0;
		Object[] params = new Object[2];
		params[0] = codPagto;

		params[1] = DataUtil.formatarData(DataUtil.HSQL_DATE, dataHora);

		StringBuffer stbQuery = new StringBuffer();
		stbQuery.append(" INSERT INTO ");
		stbQuery.append(/*SQLUtil.getDbSchema() + "."
				+*/ IVendaBilheteDAO.TABELA_BD + " (");
		stbQuery.append(IVendaBilheteDAO.COLUMN_CODIGO_PAGTO + ", ");
		stbQuery.append(IVendaBilheteDAO.COLUMN_DATA_HORA + ") ");
		stbQuery.append(" VALUES (?, ?) ");
		//
		try {
			result = SQLUtil.update(stbQuery.toString(), params);
			if (result <= 0) {
				throw new Exception(" ******* Falha na gravacao da venda!");
			}			
		}
		catch (Exception e) {
			System.err.println( e.getMessage() );
			e.printStackTrace();
			throw new Exception(" ******* Falha na gravacao da venda!" + e.getMessage());
		}
		System.out.println("\n\n\n *** VendaBilheteDAOHsql :: inserir(Date dataHora, int codPagto) \n\n\n");		
		return true;
	}

	/**
	 * inserir
	 */
	public boolean inserir(Venda venda)  throws Exception {
		int result = 0;
		ValeEntrada vale = null;
		CartaoCredito cartao = null;

		if (venda != null) {
			//-- 1o. faz insert de pagamento na base
			if (venda.getPagamento() == null) {
				throw new Exception("Venda nao cadastrada, pagamento esta nulo!");
			}

			IPagamentoDAO daoPagto = (IPagamentoDAO) DAOFactory.getImpl(IPagamentoDAO.class);

			boolean insertOK = false;
			if (venda.getPagamento().getTipo() == Pagamento.TIPO_CARTAO) {
				cartao = (CartaoCredito) venda.getPagamento();
				//INSERT especifico p/ colunas de pagamento qdo este eh por cartao
				insertOK = daoPagto.inserir(cartao);
			}
			else if (venda.getPagamento().getTipo() == Pagamento.TIPO_VALE_ENTRADA) {
				vale = (ValeEntrada) venda.getPagamento();
				//INSERT especifico p/ colunas de pagamento qdo este eh por vale
				insertOK = daoPagto.inserir(vale);
			}

			//-- 2o. obtem col. codpagto gerada p/ gravar Venda
			if (insertOK) {
				venda.getPagamento().setCodpagto( daoPagto.obterCodPagto() );
			}

			//-- 3o. gravar Venda
			Object[] params = new Object[2];
			params[0] = venda.getPagamento().getCodpagto();
			//
			if ( venda.getDataHora() == null) {
				params[1] = DataUtil.formatarData( DataUtil.HSQL_DATE, DataUtil.obterDataCorrente() );
			}
			else {
				params[1] = DataUtil.formatarData( DataUtil.HSQL_DATE, venda.getDataHora() ); 
			}

			StringBuffer stbQuery = new StringBuffer();
			stbQuery.append(" INSERT INTO ");
			stbQuery.append(/*SQLUtil.getDbSchema() + "."
					+*/ IVendaBilheteDAO.TABELA_BD + " (");
			stbQuery.append(IVendaBilheteDAO.COLUMN_CODIGO_PAGTO + ", ");
			stbQuery.append(IVendaBilheteDAO.COLUMN_DATA_HORA + ") ");
			stbQuery.append(" VALUES (?, ?) ");
			//
			result = SQLUtil.update(stbQuery.toString(), params);
			if (result <= 0) {
				throw new Exception("Falha na gravacao da venda!");
			}

			//-- 4o. gravar Bilhete(s) da Venda
			if (venda.getBilhetes() == null) {
				throw new Exception("Venda mal formulada, nao possui bilhete associado!");
			}

			IBilheteDAO daoBilhete = null;
			daoBilhete = (IBilheteDAO) DAOFactory.getImpl(IBilheteDAO.class);

			for (Bilhete bilhete : venda.getBilhetes()) {
				daoBilhete.insert(bilhete);
			}
		}
		return (result > 0 ? true : false);
	}
	
	/**
	 * 
	 * @return long
	 * @throws Exception
	 */
	public synchronized long obterProximoNumeroProtocolo() throws Exception {
		int result = 0;
		try {
			StringBuffer stbQuery = new StringBuffer();
			stbQuery.append(" SELECT MAX(" + IVendaBilheteDAO.COLUMN_CODIGO_PK
					+ ") FROM " /*+ SQLUtil.getDbSchema() + "."*/ + IVendaBilheteDAO.TABELA_BD);

			result = SQLUtil.selectCount(stbQuery.toString());
		} catch (SQLException e) {
			throw new Exception(e.getLocalizedMessage());
		}
		return (++result);
	}
}